package com.decent.web.system.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import com.decent.common.bo.MessageBean;
import com.decent.common.entity.common.Order;
import com.decent.common.entity.http.ChengQuanCode;
import com.decent.common.entity.http.ParamNode;
import com.decent.common.entity.http.ResultMessage;
import com.decent.common.entity.http.StockEntity;
import com.decent.common.enums.ErrorCodeEnum;
import com.decent.common.enums.OrderStateEnum;
import com.decent.common.exception.ErrorCodeException;
import com.decent.common.util.http.ChengHttpUtils;
import com.decent.web.config.cheng.ChengQuanConfig;
import com.decent.web.system.dao.*;
import com.decent.web.system.dto.CreateOrderDTO;
import com.decent.web.system.dto.PayOrderDTO;
import com.decent.web.system.dto.SystemOrderDTO;
import com.decent.web.system.service.SystemOrderService;
import com.decent.web.system.vo.SystemGoodsVO;
import com.decent.web.system.vo.SystemCreateOrderVO;
import com.decent.web.system.vo.SystemOrderVO;
import com.decent.web.system.vo.chengquan.ChengPayOrderVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
/**
 * @author: decent Gjh
 * @date: 2022/10/29/15:31
 * @description:
 */
@Slf4j
@Service
public class SystemOrderServiceImpl implements SystemOrderService {

    private final SystemGoodsDao goodsDao;
    private final WebUserDao userDao;
    private final SystemOrderDao orderDao;
    private final SystemBrandDao brandDao;
    private final ChengQuanConfig config;

    public SystemOrderServiceImpl(SystemGoodsDao goodsDao, WebUserDao userDao, SystemOrderDao orderDao,
                                  SystemBrandDao brandDao, ChengQuanConfig config) {
        this.goodsDao = goodsDao;
        this.userDao = userDao;
        this.orderDao = orderDao;
        this.brandDao = brandDao;
        this.config = config;
    }
    /**
     * 创建订单
     * @param createOrderDTO 订单相关信息
     * @return 订单号等信息
     */
    @Override
    public MessageBean createOrder(CreateOrderDTO createOrderDTO) {
        int maxNum=50;
        if (createOrderDTO.getNum()>maxNum){
            return MessageBean.fail("商品不存在");
        }
        //获取验证库存数
        SystemGoodsVO goods = goodsDao.selectGoodsById(createOrderDTO.getGoodsId());
        if ( goods == null ) {
            return MessageBean.fail("商品不存在");
        }
        if (goods.getStock() < createOrderDTO.getNum() || notStock(goods.getCode())){
            return MessageBean.fail("库存数量不足");
        }
        //计算价格
        BigDecimal totalPrice =   goods.getPresentPrice().multiply(new BigDecimal(createOrderDTO.getNum()));
        //验证用户的余额是否充足
        BigDecimal userMoney = userDao.getUserMoney(createOrderDTO.getUserId());
        if (userMoney == null){
            return MessageBean.fail("用户不存在");
        }
        if (userMoney.compareTo(totalPrice)<0){
            return MessageBean.fail("账户余额不足");
        }
        //创建订单
        //  根据品牌id查找所属分类
        Integer classifyId = brandDao.selectClassifyIdByBrandId(goods.getBrandId());
        String uuid = UUID.randomUUID().toString().replaceAll("-","");
        //todo 验证修改后的创建订单
        //  组合订单信息
        Order orderDTO = Order.builder()
                .userId(createOrderDTO.getUserId())
                .goodId(goods.getId())
                .goodsName(goods.getName())
                .brandId(goods.getBrandId())
                .classifyId(classifyId)
                .orderState(OrderStateEnum.UNPAID)
                .orderUuid(uuid)
                .num(createOrderDTO.getNum())
                .totalPrice(totalPrice)
                .build();
        int row = orderDao.installOrder(orderDTO);

        if (row != 0) {
            SystemCreateOrderVO systemCreateOrderVO = new SystemCreateOrderVO(uuid, totalPrice);
            return MessageBean.success(systemCreateOrderVO);
        }
        return MessageBean.fail("订单创建失败");
    }

    /**
     * 支付订单
     * @param payOrderDTO 支付订单信息
     * @return 是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public MessageBean payOrder(PayOrderDTO payOrderDTO) {
        //先查看订单uuid和用户id是否对应
        SystemOrderDTO order = orderDao.selectByUuid(payOrderDTO);
        if (Objects.isNull(order)) {
            return MessageBean.fail("订单不存在");
        }
        if ((int)order.getUserId() != payOrderDTO.getUserId()) {
            return MessageBean.fail("本订单不属于该用户");
        }
        if (order.getOrderState()==OrderStateEnum.PAID){
            return MessageBean.fail("订单已支付");
        }
        if (order.getOrderState()==OrderStateEnum.CLOSED){
            return MessageBean.fail("订单超时已被关闭");
        }
        //获取验证库存数
        SystemGoodsVO goods = goodsDao.selectGoodsById(order.getGoodId());
        if ( goods == null ) {
            return MessageBean.fail("商品已下架");
        }
        if (goods.getStock() < order.getNum() || notStock(goods.getCode())){
            return MessageBean.fail("库存数量不足");
        }
        //扣用户余额
        int row = userDao.payOrder(payOrderDTO, order);
        if (row != 1) {
            return MessageBean.fail("订单支付失败，余额不足");
        }
        // 减库存 加销量
        goodsDao.buyGoods(order.getGoodId(),order.getNum());
        //请求橙券购买
        List<ParamNode<String,Object>> params = new ArrayList<>();
        params.add(new ParamNode<>("user_order_no", order.getOrderUuid()));
        params.add(new ParamNode<>("goods_no", goods.getCode()));
        params.add(new ParamNode<>("count", order.getNum()));
        params.add(new ParamNode<>("mobile", payOrderDTO.getPhone()));
        params.add(new ParamNode<>("timestamp", System.currentTimeMillis() + ""));
        params.add(new ParamNode<>("app_id", config.getAppid()));
        String jsonResult = ChengHttpUtils.getUrl("/coupon/order/pay",params,config.getKey());
        ResultMessage<List<ChengPayOrderVO>> result = JSON.parseObject(jsonResult,
                new TypeReference<ResultMessage<List<ChengPayOrderVO>>>() {
        });
        //请求失败进行回滚
        if (result.getCode() != ChengQuanCode.SUCCESS.getCode() && result.getCode() != ChengQuanCode.ORDER_ALREADY_EXISTS.getCode()){
            throw new ErrorCodeException(ErrorCodeEnum.NO,result.getMessage());
        }
        //修改订单状态
        if (result.getCode() == ChengQuanCode.SUCCESS.getCode() && !result.getData().isEmpty()){
            ChengPayOrderVO vo = result.getData().get(0);
            order.setOrderState(OrderStateEnum.PAID);
            order.setChengOrderNo(vo.getOrderNo());
            orderDao.updateOrder(order);
            return MessageBean.success(result);
        }
        //若第一次 系统提示支付失败，但橙券已经支付成功的情况
        if (result.getCode() == ChengQuanCode.ORDER_ALREADY_EXISTS.getCode() ){
            ResultMessage<List<ChengPayOrderVO>> res = chengSelectOrderByUuid(new PayOrderDTO(order.getOrderUuid(), order.getUserId()));
            order.setOrderState(OrderStateEnum.PAID);
            order.setChengOrderNo(res.getData().get(0).getOrderNo());
            orderDao.updateOrder(order);
            return MessageBean.success(res);
        }
        return MessageBean.fail("订单创建失败");
    }

    /**
     * 查询订单
     * @param orderDTO  查询条件
     * @return 订单列表
     */
    @Override
    public MessageBean selectOrderList(SystemOrderDTO orderDTO) {
        //获取列表
        List<SystemOrderVO> orderList = orderDao.selectOrderList(orderDTO);
        if (orderList == null || orderList.isEmpty()) {
            return MessageBean.fail("暂无订单");
        }
        return MessageBean.success(orderList);
    }

    /**
     * 根据id查询订单详情
     * @param payOrderDTO 查询条件
     * @return 订单信息
     */
    @Override
    public MessageBean selectOrderByUuid(PayOrderDTO payOrderDTO) {
        SystemOrderDTO orderDTO = orderDao.selectByUuid(payOrderDTO);
        if (orderDTO.getUserId().equals(payOrderDTO.getUserId()) ){
            return MessageBean.fail("该订单不属于此用户");
        }
        if (orderDTO.getOrderState() != OrderStateEnum.PAID){
            return MessageBean.fail("订单未支付");
        }
        ResultMessage<List<ChengPayOrderVO>> result = chengSelectOrderByUuid(payOrderDTO);
        //请求失败
        if (result.getCode() != ChengQuanCode.SUCCESS.getCode()){
            return MessageBean.fail(result.getMessage());
        }
        return MessageBean.success(result.getData());
    }

    /**
     * 请求橙券查看订单
     * @param payOrderDTO 查询条件
     * @return 订单信息
     */
    public ResultMessage<List<ChengPayOrderVO>> chengSelectOrderByUuid(PayOrderDTO payOrderDTO){
        List<ParamNode<String,Object>> params = new ArrayList<>();
        params.add(new ParamNode<>("user_order_no", payOrderDTO.getOrderUuid()));
        params.add(new ParamNode<>("timestamp", System.currentTimeMillis() + ""));
        params.add(new ParamNode<>("app_id", config.getAppid()));
        String jsonResult = ChengHttpUtils.getUrl("/coupon/order/query",params,config.getKey());
        return JSON.parseObject(jsonResult,
                new TypeReference<ResultMessage<List<ChengPayOrderVO>>>() {
                });
    }


    /**
     * 判断是否有库存
     * @param goodsId 商品id
     * @return 是否有库存
     */
    private boolean notStock(String goodsId){
        List<ParamNode<String, Object>> params = new ArrayList<>();
        params.add(new ParamNode<>("goods_no", goodsId));
        params.add(new ParamNode<>("timestamp", System.currentTimeMillis() + ""));
        params.add(new ParamNode<>("app_id", config.getAppid()));
        String jsonResult = ChengHttpUtils.getUrl("/coupon/goods/stock", params, config.getKey());
        ResultMessage<StockEntity> result = JSON.parseObject(jsonResult,
                new TypeReference<ResultMessage<StockEntity>>(StockEntity.class) {
                });
        if (result.getCode() == ChengQuanCode.SUCCESS.getCode()) {
            return result.getData().getStockNum() <= 0;
        }
        return true;
    }
}
